//
//  ZLMoneyField.swift
//  nf-ios
//
//  Created by itzhaolei on 2021/9/6.
//

import Foundation

open class ZLMoneyField: UITextField {
    
    // 配置
    private lazy var realityHeight: CGFloat = {
        ZLLocalAutoScale(217.0)
    }()
    private let bgColor: UIColor = .init(red: 0.82, green: 0.82, blue: 0.84, alpha: 1.0)
    private let forbiddenColor: UIColor = .init(red: 0.65, green: 0.65, blue: 0.67, alpha: 1.0)
    private let touchColor: UIColor = .init(red: 0.78, green: 0.78, blue: 0.80, alpha: 1.0)
    
    private lazy var unitView: UIView = {
        let view = UIView(frame: .init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: realityHeight + 30.0))
        view.backgroundColor = bgColor
        addKeys(unitView: view)
        return view
    }()
    private var doneItem: UIButton = .init()
    private var pointItem: UIButton = .init()
    
    private var changed: ((_ text: String) -> Void)?
    private var done: ((_ text: String) -> Void)?
    private var color: UIColor = .orange
    private var floatCount: Int
    private var isOnRestRange: Bool = false
    private var items: [UIButton] = []
    public init(frame: CGRect, color: UIColor, floatCount: Int = 2, changed: ((_ text: String) -> Void)?, done: ((_ text: String) -> Void)?) {
        self.changed = changed
        self.done = done
        self.color = color
        self.floatCount = floatCount
        super.init(frame: frame)
        self.inputView = unitView
    }
    
    open override var text: String? {
        didSet {
            changed?(text ?? "")
            doneItem.backgroundColor = (text?.count ?? 0) > 0 ? color : forbiddenColor
            doneItem.isEnabled = (text?.count ?? 0) > 0
        }
    }
    
    required public init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
    
    @discardableResult
    open override func becomeFirstResponder() -> Bool {
        let isCan = super.becomeFirstResponder()
        checkPointItemEnable()
        return isCan
    }
    
    open override var selectedTextRange: UITextRange? {
        didSet {
            checkPointItemEnable()
        }
    }
        
}

private extension ZLMoneyField {
    
    func ZLLocalAutoScale(_ value: CGFloat) -> CGFloat {
        let referWidth: CGFloat = 375.0
        let referHeight: CGFloat = 217.0
        let realityWidth: CGFloat = UIScreen.main.bounds.width
        let realityHeight: CGFloat = realityWidth * (referHeight / referWidth)
        let scale = ((realityHeight + realityWidth) / (referHeight + referWidth)) * value
        return scale
    }
        
    func addKeys(unitView: UIView) {
        let names: [String] = ["1","2","3","4","5","6","7","8","9",".","0","","","确定"]
        let screenWidth: CGFloat = UIScreen.main.bounds.width
        let space: CGFloat = ZLLocalAutoScale(7.0)
        for index in 0..<names.count {
            var frame: CGRect = .zero
            let maxItemWidth: CGFloat = realityHeight / 2.0 - space
            let maxItemHeight: CGFloat = (realityHeight - space * 2) / 2.0
            let minItemWidth: CGFloat = (screenWidth - realityHeight / 2.0 - space * 4) / 3
            let minItemHeight: CGFloat = (realityHeight - space * 4) / 4
            if index == names.count - 1 {
                frame = .init(x: screenWidth - maxItemWidth - space, y: space * 2 + maxItemHeight, width: maxItemWidth, height: maxItemHeight)
            }else if (index == names.count - 2) {
                frame = .init(x: screenWidth - maxItemWidth - space, y: space, width: maxItemWidth, height: maxItemHeight)
            }else {
                frame = .init(x: space + (minItemWidth + space) * CGFloat((index % 3)), y: space + (minItemHeight + space) * CGFloat((index / 3)), width: minItemWidth, height: minItemHeight)
                if floatCount == 0 {
                    let lackingWidth: CGFloat = (screenWidth - realityHeight / 2.0 - space * 3) / 2
                    if (index == names.count - 3 || index == names.count - 4) {
                        frame = .init(x: space + (lackingWidth + space) * CGFloat((index % 2)), y: space + (minItemHeight + space) * CGFloat((index / 3)), width: lackingWidth, height: minItemHeight)
                    }
                }
            }
            let button = UIButton(frame: frame)
            button.backgroundColor = .white
            button.isEnabled = true
            if index == names.count - 1 {
                button.setTitle(names[index], for: .normal)
                button.titleLabel?.font = .systemFont(ofSize: ZLLocalAutoScale(22.0))
                button.setTitleColor(.white, for: .normal)
                button.addTarget(self, action: #selector(doneAction(_:)), for: .touchUpInside)
                button.backgroundColor = forbiddenColor
                button.isEnabled = false
                self.doneItem = button
            }else if (index == names.count - 2) {
                let image = Resources.image("清除")
                button.setImage(image, for: .normal)
                button.addTarget(self, action: #selector(deleteAction(_:)), for: .touchUpInside)
            }else if (index == names.count - 3) {
                let image = Resources.image("键盘")
                button.setImage(image, for: .normal)
                button.addTarget(self, action: #selector(closeAction(_:)), for: .touchUpInside)
            }else {
                button.setTitle(names[index], for: .normal)
                button.titleLabel?.font = .boldSystemFont(ofSize: ZLLocalAutoScale(18.0))
                button.setTitleColor(.black, for: .normal)
                button.addTarget(self, action: #selector(itemAction(_:)), for: .touchUpInside)
                if floatCount == 0 {
                    if index == names.count - 5 {
                        button.isHidden = true
                    }
                }
                if index == names.count - 5 {
                    self.pointItem = button
                }
            }
            button.layer.cornerRadius = 6.0
            unitView.addSubview(button)
            items.append(button)
        }
    }
    
    func checkPointItemEnable() {
        // 排除重置
        if isOnRestRange {
            return
        }
        let location = self.offset(from: beginningOfDocument, to: selectedTextRange?.start ?? .init())
        let fieldText: NSString = ((text ?? "") as NSString)
        let existPoint = fieldText.range(of: ".").location != NSNotFound
        // 排查是不是已经存在小数点（不能存在两个小数点）、或者避免产生超出限制小数的个数
        if existPoint || location < fieldText.length - floatCount {
            // 不再允许输入小数点
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.06, execute: {[weak self] in
                // 在按键反馈效果完成后，将小数点调整为不可点击的状态
                guard let self = self else { return }
                for button in self.items {
                    let index = self.items.firstIndex(of: button) ?? 0
                    if index == self.items.count - 5 {
                        button.isEnabled = false
                        button.backgroundColor = self.forbiddenColor
                    }else {
                        if index == self.items.count - 1 {
                            button.backgroundColor = (self.text?.count ?? 0) > 0 ? self.color : self.forbiddenColor
                            button.isEnabled = (self.text?.count ?? 0) > 0
                        }else {
                            button.isEnabled = true
                            button.backgroundColor = .white
                        }
                    }
                }
                
            })
            return
        }
        // 正常的数值
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.06, execute: {[weak self] in
            // 在按键反馈效果完成后，调整为不可点击的状态
            guard let self = self else { return }
            for button in self.items {
                let index = self.items.firstIndex(of: button) ?? 0
                if index == self.items.count - 1 {
                    button.backgroundColor = (self.text?.count ?? 0) > 0 ? self.color : self.forbiddenColor
                    button.isEnabled = (self.text?.count ?? 0) > 0
                }else {
                    button.isEnabled = true
                    button.backgroundColor = .white
                }
            }
        })
    }
    
    @objc func doneAction(_ sender: UIButton) {
        clickAnimation(sender)
        self.text = checkValidityAndRepair(text: text ?? "")
        done?(self.text ?? "")
        resignFirstResponder()
    }
    
    @objc func closeAction(_ sender: UIButton) {
        clickAnimation(sender)
        self.text = checkValidityAndRepair(text: text ?? "")
        resignFirstResponder()
    }
    
    /// 检查有效性并修复
    /// - Parameter onlyInt: 普通按钮就只修复整数部分，如果是关联关闭事件的按钮，就全部进行检查修复
    func checkValidityAndRepair(_ onlyInt: Bool = false, text: String) -> String {
        let fieldText: NSString = (text as NSString)
        let existPoint = fieldText.range(of: ".").location != NSNotFound
        if existPoint {
            let values = fieldText.components(separatedBy: ".")
            let intValue: Int64 = Int64(values.first ?? "") ?? 0
            let value: String = String(format: "%.\(floatCount)f", Double("0.\(values.last ?? "")") ?? 0)
            let floatValue = (value as NSString).components(separatedBy: ".").last ?? ""
            let originFloatValue = values.last ?? ""
            return "\(intValue).\(onlyInt ? originFloatValue : floatValue)"
        }
        return "\(Int64(text) ?? 0)"
    }
    
    @objc func deleteAction(_ sender: UIButton) {
        clickAnimation(sender)
        let fieldText: NSString = ((text ?? "") as NSString)
        let location = self.offset(from: beginningOfDocument, to: selectedTextRange?.start ?? .init())
        if fieldText.length > 0 && location > 0 {
            var newText = fieldText.replacingCharacters(in: .init(location: location - 1, length: 1), with: "")
            var zeroStart: Bool = false
            if let safeString = newText as? NSString {
                if newText.first == "0" && fieldText.substring(to: 2) != "0." {
                    if safeString.range(of: ".").location != NSNotFound {
                        let values = safeString.components(separatedBy: ".")
                        newText = "\(Int64(values.first ?? "") ?? 0).\(values.last ?? "")"
                        zeroStart = true
                    }else {
                        newText = "\(Int64(newText) ?? 0)"
                        zeroStart = true
                    }
                }
            }
            self.text = newText
            // 回滚光标为初始位置
            let begin = beginningOfDocument
            let start = position(from: begin, offset: 0)
            let range = textRange(from: start ?? .init(), to: start ?? .init())
            isOnRestRange = true
            selectedTextRange = range
            isOnRestRange = false
            if zeroStart {
                return
            }
            // 调整偏移量
            var currentOffset = offset(from: endOfDocument, to: selectedTextRange?.end ?? .init())
            currentOffset += (location - 1)
            let newPos = position(from: endOfDocument, offset: currentOffset)
            selectedTextRange = textRange(from: newPos ?? .init(), to: newPos ?? .init())
        }
    }
    
    @objc func itemAction(_ sender: UIButton) {
        clickAnimation(sender)
        let senderText: NSString = ((sender.titleLabel?.text ?? "") as NSString)
        let fieldText: NSString = ((text ?? "") as NSString)
        let existPoint = fieldText.range(of: ".").location != NSNotFound
        if senderText == "." && existPoint {
            return
        }
        let location = offset(from: beginningOfDocument, to: selectedTextRange?.start ?? .init())
        if existPoint {
            let values = fieldText.components(separatedBy: ".")
            if values.last?.count ?? 0 >= floatCount && location > values.first?.count ?? 0 {
                return
            }
        }
        let importText: String = sender.titleLabel?.text ?? ""
        self.text = checkValidityAndRepair(true, text: fieldText.replacingCharacters(in: .init(location: location, length: 0), with: importText))
        // 回滚光标为初始位置
        let begin = beginningOfDocument
        let start = position(from: begin, offset: 0)
        let range = textRange(from: start ?? .init(), to: start ?? .init())
        isOnRestRange = true
        selectedTextRange = range
        isOnRestRange = false
        // 调整偏移量
        let selectedRange = selectedTextRange
        var currentOffset = offset(from: endOfDocument, to: selectedRange?.end ?? .init())
        currentOffset += (location + importText.count)
        let newPos = position(from: endOfDocument, offset: currentOffset)
        guard let _ = newPos else {
            currentOffset = ((text ?? "") as NSString).length - 1
            let newPos = position(from: endOfDocument, offset: currentOffset)
            selectedTextRange = textRange(from: newPos ?? .init(), to: newPos ?? .init())
            return }
        selectedTextRange = textRange(from: newPos ?? .init(), to: newPos ?? .init())
    }
    
    func clickAnimation(_ sender: UIButton) {
        sender.backgroundColor = touchColor
        weak var weakSender = sender
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.05, execute: {
            weakSender?.backgroundColor = .white
        })
    }
    
}

